
// 生成 tx 时钟

module tx_clk_en_gen( 

	input 		reset_i,
    input 		speed10_100_i,
    input 		speed100_i,
    input		clk_i,				// 125mhz
    output reg	client_tx_c_en_o_r,
    output reg 	gmii_tx_c_en_o_r,
    output reg 	rgmii_tx_c_en_o_r,
    output reg 	rgmii_tx_c_en_shift_o_r
);


// 模块内部信号
reg			[5:0]		counter_6b_r;
reg			[5:0]		divide_6b_r;
reg			[5:0]		first_edge_6b_r;
reg			[5:0]		second_edge_6b_r;
reg						client_tx_c_en_int_r;


wire					speed10_100_int_w;			// 10 100兆同步信号
wire					speed100_int_w;				// 100 兆同步信号


reg						rgmii_tx_c_en_int_r;		// 发送端同步时钟，快时钟
reg						rgmii_tx_c_en_shift_int_r;	// 发送端同步时钟，慢时钟


// 异步信号转同步信号
sync_block speed_10_100_sync
(
  	.clk_i(clk_i),
    .data_i(speed10_100_i),
    .data_o(speed10_100_int_w)  
);

// 异步信号转同步信号
sync_block speed_100_sync
(
  	.clk_i(clk_i),
    .data_i(speed100_i),
    .data_o(speed100_int_w)  
);


// 产生一个6位计数器，然后 计算时钟（取决于 speed 值）
always @(posedge clk_i) begin
	if(reset_i) begin
    	counter_6b_r <= 0;
    end
    else begin
    	if(counter_6b_r >= divide_6b_r) begin
        	counter_6b_r <= 0;
        end
        else begin
        	counter_6b_r <= counter_6b_r + 1;
        end
    end
end

// speed值产生变化时，调整输出时钟
always @(speed10_100_int_w or speed100_int_w) begin
	if(!speed10_100_int_w) begin
    	divide_6b_r <= 0;
        first_edge_6b_r <= 0;
        second_edge_6b_r <= 0;
    end
    else begin
    	if(speed100_int_w) begin
        	divide_6b_r <= 4;
            first_edge_6b_r <= 1;
            second_edge_6b_r = 2;
        end 
        else begin
        	divide_6b_r <= 49;
            first_edge_6b_r <= 23;
            second_edge_6b_r <= 24;
        end
    end
end


// 产生 rgmii tx 使能信号
always @(posedge clk_i) begin

	if(reset_i) begin
    	rgmii_tx_c_en_int_r <= 0;
        rgmii_tx_c_en_shift_int_r <=0;
    end
    else begin
    
    	// 100 / 10 Mbs
    	if(speed10_100_int_w) begin
        	if(counter_6b_r >= divide_6b_r)begin
            	rgmii_tx_c_en_int_r <= 1;
                rgmii_tx_c_en_shift_int_r <= 1;
            end
            
            // rgmii_txc_en_shift_int高电平持续时间比rgmii_txc_en_int多一拍
            else if(counter_6b_r == first_edge_6b_r) begin
            	rgmii_tx_c_en_int_r <= 0;
                rgmii_tx_c_en_shift_int_r <= 1;
            end
            else if(counter_6b_r == second_edge_6b_r) begin
            	rgmii_tx_c_en_int_r <= 0;
                rgmii_tx_c_en_shift_int_r <= 0;
            end
        end
        else begin	
        	// 1Gbps
	        // 在rgmii_interface模块中输入给ODDR，产生rgmii_txc=125MHz
        	rgmii_tx_c_en_int_r <= 0;
            rgmii_tx_c_en_shift_int_r <= 1;
        end
    end
	
end


//需要控制使能和时钟之间的流水线延迟，以确保IO的正确时序
always @(posedge clk_i) begin
	
    if(reset_i) begin
    
    	rgmii_tx_c_en_o_r <= 0;
        rgmii_tx_c_en_shift_o_r <= 0;
        
    end
    else begin
    	
        rgmii_tx_c_en_o_r <= rgmii_tx_c_en_int_r;
        rgmii_tx_c_en_shift_o_r <= rgmii_tx_c_en_shift_int_r;
        
    end

end


// 输出时钟使能信号
always @(posedge clk_i) begin

	if(reset_i) begin
    	client_tx_c_en_int_r <= 0;
    end
    else begin
    
    	if(speed10_100_int_w) begin
        
        	if(counter_6b_r >= divide_6b_r) begin
            	
                client_tx_c_en_int_r <= !client_tx_c_en_int_r;
                
            end
        end
        else begin
        	client_tx_c_en_int_r <= 1;
        end
    
    end

end



always @(posedge clk_i) begin

	if(reset_i) begin
	    client_tx_c_en_o_r <= 0;
        gmii_tx_c_en_o_r <= 0;
    end
    else begin
    
    	// 100Mbps对应产生 gmii_txcen_o = 25MHz,
        // 10Mbps对应产生 gmii_txcen_o = 2.5MHz
        // 1Gbps时：divide_val = 0；counter = 0; 对应产生 gmii_tx_c_en_o_r = 1; 对应产生 gmii_tx_clk = 125MHz
    	if(counter_6b_r >= divide_6b_r) begin
        	gmii_tx_c_en_o_r <= 1;			// gmii_tx_c_en_o_r 一个周期（8ns）高电平
        end
        else begin
        	gmii_tx_c_en_o_r <= 0;
        end
    end
    
    
    // 100Mbps对应产生 client_tx = 12.5MHz,
    // 10Mbps对应产生 client_tx = 1.25MHz
    // 1Gbps时：divide_val = 0；counter = 0; 对应产生 client_tx_c_en_o_r = 1;  对应产生client_txc =125MHz
    if((counter_6b_r >= divide_6b_r) & !client_tx_c_en_int_r) begin
    	client_tx_c_en_o_r <= 1;
    end
    else begin
    	client_tx_c_en_o_r <= 0;
    end

end


endmodule
















